﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;

namespace HorrorEncodeLib {
    /// <summary>
    /// El Encode Map (Mapa de Codificación) utilizado para realizar la codificación del mensaje
    /// corresponde al tipo de carácteres que se reciben (si todos son mayúsuculas, si contiene
    /// símbolos, si tiene una mezcla entre mayúsculas y minúsculas, etc.) para codificar y que
    /// permite obtener buen porcentaje de compresión.
    /// </summary>
    public enum EncodeMappings {
        FullCaseExc,   // + Mayúsculas + Minúsculas - Símbolos
        FullCaseFull,  // + Mayúsculas + Minúsculas + Símbolos
        UpperCaseExc,  // + Mayúsculas - Minúsculas - Símbolos
        UpperCaseFull, // + Mayúsculas - Minúsculas + Símbolos
        LowerCaseExc,  // - Mayúsculas + Minúsculas - Símbolos
        LowerCaseFull, // - Mayúsculas - Minúsculas + Símbolos
        SmartMapping   // Automáticamente determina uno de los anteriores
    }

    /// <summary>
    /// Contiene los Encode Maps (Mapas de Codificación) con los que se codifican los
    /// Mensajes. Éstos fueron generados a partir de un Análisis de Frecuencias realizado
    /// sobre un día entero de Tweets en Español que posteriormente se utilizaron para
    /// generar un Árbol de Huffman.
    /// 
    /// Por ello, la compresión (menos bits representan más información) no es la misma
    /// cuando se utilizan otros idiomas.
    /// </summary>
    internal class EncodeMaps {
        // --- Algunas constantes ---

        // Bits para 0 y 1 de una forma más gráfica (para que se entienda mejor)
        protected const bool A = true;
        protected const bool a = false;

        /// <summary>
        /// Tamaño (número de bits) de las cabeceras de Encode Map (Mapa de Codificación)
        /// </summary>
        public const int HeadersSize = 3;

        /// <summary>
        /// Los símbolos que puede codificar el algoritmo
        /// </summary>
        public const string SupportedSymbols = "!\"#$%&()*,./:;?@[\\]^_|}~¡+<=>0'1-23456789";

        /// <summary>
        /// Las letras que puede codificar el algoritmo
        /// </summary>
        public const string SupportedLetters = "abcdefghijklmnñopqrstuvwxyzABCDEFGHIJKLMNÑOPQRSTUVWXYZ";


        // --- Propiedades Privadas ---

        // Los Encode Maps (Mapas de Codificación) se almacenan aquí, y se inicializan al acceder
        // a las propiedades públicas
        protected static Dictionary<EncodeMappings, BitArray> _encodeMapHeaders = new Dictionary<EncodeMappings, BitArray>();
        protected static Dictionary<EncodeMappings, Dictionary<char, BitArray>> _encodeMaps = new Dictionary<EncodeMappings, Dictionary<char, BitArray>>();


        // --- Propiedades Públicas ---

        /// <summary>
        /// Las cabeceras de los Encode Maps (Mapas de Codificación) utilizados para identificar la
        /// codificación del mensaje.
        /// </summary>
        public static Dictionary<EncodeMappings, BitArray> Headers {
            get {
                if ( _encodeMapHeaders.Count > 0 )
                    return _encodeMapHeaders;
                else
                    return InitEncodeMapHeaders();
            }
        }

        /// <summary>
        /// Los Encode Maps (Mapas de Codificación) utilizados para codificar y decodificar mensajes.
        /// </summary>
        public static Dictionary<EncodeMappings, Dictionary<char, BitArray>> Maps {
            get {
                if ( _encodeMaps.Count > 0 )
                    return _encodeMaps;
                else
                    return InitEncodeMaps();
            }
        }


        // --- Métodos Públicos ---

        /// <summary>
        /// Determina cuál es el mejor Encode Map (Mapa de Codificación) para una cadena
        /// </summary>
        /// <param name="obj">Cadena para la cual determinar el Encode Map (Mapa de Codificación)</param>
        /// <returns>El Encode Map (Mapa de Codificación) que se ajusta a la cadena</returns>
        public static EncodeMappings GetSmartMap(string obj) {
            // > Inicializar algunas banderas mágicas
            bool isUpperCase = false;
            bool isLowerCase = false;
            bool hasSymbols  = false;

            // > Determinar el uso de Mayúsculas y Minúsculas
            if ( obj.ToUpper() == obj )
                isUpperCase = true;
            if ( obj.ToLower() == obj )
                isLowerCase = true;
            if ( !isUpperCase && !isLowerCase ) {
                isUpperCase = true;
                isLowerCase = true;
            }

            // > Determinar el uso de símbolos
            foreach ( char chr in SupportedSymbols )
                if ( obj.IndexOf(chr) > -1 ) {
                    hasSymbols = true;
                    break;
                }

            // > Devolver el Encode Map (Mapa de Codificación) detectado
            if ( isUpperCase && isLowerCase && hasSymbols )
                return EncodeMappings.FullCaseFull;
            else if ( isUpperCase && isLowerCase )
                return EncodeMappings.FullCaseExc;
            else if ( isUpperCase && hasSymbols )
                return EncodeMappings.UpperCaseFull;
            else if ( isLowerCase && hasSymbols )
                return EncodeMappings.LowerCaseFull;
            else if ( isUpperCase )
                return EncodeMappings.UpperCaseExc;
            else
                return EncodeMappings.LowerCaseExc;
        }


        // --- Métodos Privados ---

        /// <summary>
        /// Definir las cabeceras de los Encode Maps (Mapas de Codificación) que identifican el
        /// tipo de codificación utilizado en los mensajes.
        /// </summary>
        /// <returns></returns>
        protected static Dictionary<EncodeMappings, BitArray> InitEncodeMapHeaders() {
            // Aquí definimos las cabeceras de los Encode Maps (Mapas de Codificación)
            _encodeMapHeaders.Add(EncodeMappings.FullCaseExc  , new BitArray(new bool[] { A, a, a }));
            _encodeMapHeaders.Add(EncodeMappings.FullCaseFull , new BitArray(new bool[] { a, A, a }));
            _encodeMapHeaders.Add(EncodeMappings.UpperCaseExc , new BitArray(new bool[] { A, A, a }));
            _encodeMapHeaders.Add(EncodeMappings.UpperCaseFull, new BitArray(new bool[] { a, a, A }));
            _encodeMapHeaders.Add(EncodeMappings.LowerCaseFull, new BitArray(new bool[] { A, a, A }));
            _encodeMapHeaders.Add(EncodeMappings.LowerCaseExc , new BitArray(new bool[] { a, A, A }));

            // Devolver las cabeceras de los Encode Maps (Mapas de Codificación)
            return _encodeMapHeaders;
        }

        /// <summary>
        /// Definir los Encode Maps (Mapas de Codificación) que se utilizan para codificar y
        /// decodificar mensajes.
        /// </summary>
        /// <returns></returns>
        protected static Dictionary<EncodeMappings, Dictionary<char, BitArray>> InitEncodeMaps() {
            // Contiene temporalmente el EncodeMap (Mapa de Codificación) que se
            // genera en los siguientes checkpoints
            Dictionary<char, BitArray> thisMap;

            // -- Full Case Exc Map --
            #region "Full Case Exc Map"
            thisMap = new Dictionary<char, BitArray>();
            thisMap.Add('r', new BitArray(new bool[] { a, a, a, a }));
            thisMap.Add('i', new BitArray(new bool[] { a, a, a, A }));
            thisMap.Add('e', new BitArray(new bool[] { a, a, A }));
            thisMap.Add('a', new BitArray(new bool[] { a, A, a }));
            thisMap.Add('n', new BitArray(new bool[] { a, A, A, a }));
            thisMap.Add('s', new BitArray(new bool[] { a, A, A, A }));
            thisMap.Add('m', new BitArray(new bool[] { A, a, a, a, a }));
            thisMap.Add('c', new BitArray(new bool[] { A, a, a, a, A }));
            thisMap.Add('R', new BitArray(new bool[] { A, a, a, A, a, a, a, a }));
            thisMap.Add('T', new BitArray(new bool[] { A, a, a, A, a, a, a, A }));
            thisMap.Add('ñ', new BitArray(new bool[] { A, a, a, A, a, a, A, a, a, a, a }));
            thisMap.Add('K', new BitArray(new bool[] { A, a, a, A, a, a, A, a, a, a, A }));
            thisMap.Add('F', new BitArray(new bool[] { A, a, a, A, a, a, A, a, a, A }));
            thisMap.Add('P', new BitArray(new bool[] { A, a, a, A, a, a, A, a, A }));
            thisMap.Add('w', new BitArray(new bool[] { A, a, a, A, a, a, A, A, a }));
            thisMap.Add('Y', new BitArray(new bool[] { A, a, a, A, a, a, A, A, A, a }));
            thisMap.Add('G', new BitArray(new bool[] { A, a, a, A, a, a, A, A, A, A }));
            thisMap.Add('N', new BitArray(new bool[] { A, a, a, A, a, A, a, a, a }));
            thisMap.Add('L', new BitArray(new bool[] { A, a, a, A, a, A, a, a, A }));
            thisMap.Add('A', new BitArray(new bool[] { A, a, a, A, a, A, a, A }));
            thisMap.Add('z', new BitArray(new bool[] { A, a, a, A, a, A, A, a }));
            thisMap.Add('C', new BitArray(new bool[] { A, a, a, A, a, A, A, A, a }));
            thisMap.Add('O', new BitArray(new bool[] { A, a, a, A, a, A, A, A, A }));
            thisMap.Add('d', new BitArray(new bool[] { A, a, a, A, A }));
            thisMap.Add('u', new BitArray(new bool[] { A, a, A, a, a }));
            thisMap.Add('l', new BitArray(new bool[] { A, a, A, a, A }));
            thisMap.Add('o', new BitArray(new bool[] { A, a, A, A }));
            thisMap.Add('v', new BitArray(new bool[] { A, A, a, a, a, a, a }));
            thisMap.Add('H', new BitArray(new bool[] { A, A, a, a, a, a, A, a, a, a }));
            thisMap.Add('U', new BitArray(new bool[] { A, A, a, a, a, a, A, a, a, A }));
            thisMap.Add('D', new BitArray(new bool[] { A, A, a, a, a, a, A, a, A }));
            thisMap.Add('x', new BitArray(new bool[] { A, A, a, a, a, a, A, A, a }));
            thisMap.Add('B', new BitArray(new bool[] { A, A, a, a, a, a, A, A, A, a }));
            thisMap.Add('W', new BitArray(new bool[] { A, A, a, a, a, a, A, A, A, A, a, a }));
            thisMap.Add('X', new BitArray(new bool[] { A, A, a, a, a, a, A, A, A, A, a, A }));
            thisMap.Add('Z', new BitArray(new bool[] { A, A, a, a, a, a, A, A, A, A, A, a }));
            thisMap.Add('Ñ', new BitArray(new bool[] { A, A, a, a, a, a, A, A, A, A, A, A }));
            thisMap.Add('p', new BitArray(new bool[] { A, A, a, a, a, A }));
            thisMap.Add('t', new BitArray(new bool[] { A, A, a, a, A }));
            thisMap.Add('q', new BitArray(new bool[] { A, A, a, A, a, a, a }));
            thisMap.Add('b', new BitArray(new bool[] { A, A, a, A, a, a, A }));
            thisMap.Add('M', new BitArray(new bool[] { A, A, a, A, a, A, a, a, a }));
            thisMap.Add('S', new BitArray(new bool[] { A, A, a, A, a, A, a, a, A }));
            thisMap.Add('k', new BitArray(new bool[] { A, A, a, A, a, A, a, A, a }));
            thisMap.Add('.', new BitArray(new bool[] { A, A, a, A, a, A, a, A, A, a }));
            thisMap.Add('J', new BitArray(new bool[] { A, A, a, A, a, A, a, A, A, A }));
            thisMap.Add('g', new BitArray(new bool[] { A, A, a, A, a, A, A }));
            thisMap.Add('y', new BitArray(new bool[] { A, A, a, A, A, a, a }));
            thisMap.Add('j', new BitArray(new bool[] { A, A, a, A, A, a, A }));
            thisMap.Add('f', new BitArray(new bool[] { A, A, a, A, A, A, a, a }));
            thisMap.Add('I', new BitArray(new bool[] { A, A, a, A, A, A, a, A, a, a }));
            thisMap.Add('Q', new BitArray(new bool[] { A, A, a, A, A, A, a, A, a, A, a }));
            thisMap.Add('V', new BitArray(new bool[] { A, A, a, A, A, A, a, A, a, A, A }));
            thisMap.Add('E', new BitArray(new bool[] { A, A, a, A, A, A, a, A, A }));
            thisMap.Add('h', new BitArray(new bool[] { A, A, a, A, A, A, A }));
            thisMap.Add(' ', new BitArray(new bool[] { A, A, A }));
            _encodeMaps.Add(EncodeMappings.FullCaseExc, thisMap);
            #endregion

            // -- Full Case Full Map --
            #region "Full Case Full Map"
            thisMap = new Dictionary<char, BitArray>();
            thisMap.Add('e', new BitArray(new bool[] { a, a, a }));
            thisMap.Add('i', new BitArray(new bool[] { a, a, A, a }));
            thisMap.Add('n', new BitArray(new bool[] { a, a, A, A }));
            thisMap.Add('a', new BitArray(new bool[] { a, A, a }));
            thisMap.Add('s', new BitArray(new bool[] { a, A, A, a }));
            thisMap.Add('m', new BitArray(new bool[] { a, A, A, A, a }));
            thisMap.Add('c', new BitArray(new bool[] { a, A, A, A, A }));
            thisMap.Add(':', new BitArray(new bool[] { A, a, a, a, a, a, a, a, a }));
            thisMap.Add('V', new BitArray(new bool[] { A, a, a, a, a, a, a, a, A, a }));
            thisMap.Add('0', new BitArray(new bool[] { A, a, a, a, a, a, a, a, A, A }));
            thisMap.Add('!', new BitArray(new bool[] { A, a, a, a, a, a, a, A }));
            thisMap.Add('P', new BitArray(new bool[] { A, a, a, a, a, a, A, a, a }));
            thisMap.Add('w', new BitArray(new bool[] { A, a, a, a, a, a, A, a, A }));
            thisMap.Add('F', new BitArray(new bool[] { A, a, a, a, a, a, A, A, a, a }));
            thisMap.Add('Y', new BitArray(new bool[] { A, a, a, a, a, a, A, A, a, A }));
            thisMap.Add('9', new BitArray(new bool[] { A, a, a, a, a, a, A, A, A, a, a }));
            thisMap.Add('K', new BitArray(new bool[] { A, a, a, a, a, a, A, A, A, a, A }));
            thisMap.Add('G', new BitArray(new bool[] { A, a, a, a, a, a, A, A, A, A }));
            thisMap.Add('.', new BitArray(new bool[] { A, a, a, a, a, A, a }));
            thisMap.Add('N', new BitArray(new bool[] { A, a, a, a, a, A, A, a, a }));
            thisMap.Add('L', new BitArray(new bool[] { A, a, a, a, a, A, A, a, A }));
            thisMap.Add('A', new BitArray(new bool[] { A, a, a, a, a, A, A, A }));
            thisMap.Add('d', new BitArray(new bool[] { A, a, a, a, A }));
            thisMap.Add('u', new BitArray(new bool[] { A, a, a, A, a }));
            thisMap.Add('z', new BitArray(new bool[] { A, a, a, A, A, a, a, a }));
            thisMap.Add('(', new BitArray(new bool[] { A, a, a, A, A, a, a, A, a, a }));
            thisMap.Add('¡', new BitArray(new bool[] { A, a, a, A, A, a, a, A, a, A }));
            thisMap.Add('C', new BitArray(new bool[] { A, a, a, A, A, a, a, A, A }));
            thisMap.Add(';', new BitArray(new bool[] { A, a, a, A, A, a, A, a, a, a, a, a }));
            thisMap.Add('$', new BitArray(new bool[] { A, a, a, A, A, a, A, a, a, a, a, A, a }));
            thisMap.Add('%', new BitArray(new bool[] { A, a, a, A, A, a, A, a, a, a, a, A, A }));
            thisMap.Add('\'', new BitArray(new bool[] { A, a, a, A, A, a, A, a, a, a, A, a }));
            thisMap.Add('6', new BitArray(new bool[] { A, a, a, A, A, a, A, a, a, a, A, A }));
            thisMap.Add('1', new BitArray(new bool[] { A, a, a, A, A, a, A, a, a, A }));
            thisMap.Add('O', new BitArray(new bool[] { A, a, a, A, A, a, A, a, A }));
            thisMap.Add('H', new BitArray(new bool[] { A, a, a, A, A, a, A, A, a, a }));
            thisMap.Add('U', new BitArray(new bool[] { A, a, a, A, A, a, A, A, a, A }));
            thisMap.Add('D', new BitArray(new bool[] { A, a, a, A, A, a, A, A, A }));
            thisMap.Add('v', new BitArray(new bool[] { A, a, a, A, A, A, a }));
            thisMap.Add('q', new BitArray(new bool[] { A, a, a, A, A, A, A }));
            thisMap.Add('o', new BitArray(new bool[] { A, a, A, a }));
            thisMap.Add('l', new BitArray(new bool[] { A, a, A, A, a }));
            thisMap.Add('t', new BitArray(new bool[] { A, a, A, A, A }));
            thisMap.Add(' ', new BitArray(new bool[] { A, A, a }));
            thisMap.Add('p', new BitArray(new bool[] { A, A, A, a, a, a }));
            thisMap.Add('x', new BitArray(new bool[] { A, A, A, a, a, A, a, a, a }));
            thisMap.Add('B', new BitArray(new bool[] { A, A, A, a, a, A, a, a, A, a }));
            thisMap.Add('W', new BitArray(new bool[] { A, A, A, a, a, A, a, a, A, A, a, a }));
            thisMap.Add('X', new BitArray(new bool[] { A, A, A, a, a, A, a, a, A, A, a, A }));
            thisMap.Add('Z', new BitArray(new bool[] { A, A, A, a, a, A, a, a, A, A, A, a }));
            thisMap.Add('&', new BitArray(new bool[] { A, A, A, a, a, A, a, a, A, A, A, A, a, a }));
            thisMap.Add('+', new BitArray(new bool[] { A, A, A, a, a, A, a, a, A, A, A, A, a, A }));
            thisMap.Add('<', new BitArray(new bool[] { A, A, A, a, a, A, a, a, A, A, A, A, A, a }));
            thisMap.Add('=', new BitArray(new bool[] { A, A, A, a, a, A, a, a, A, A, A, A, A, A }));
            thisMap.Add('M', new BitArray(new bool[] { A, A, A, a, a, A, a, A, a }));
            thisMap.Add('#', new BitArray(new bool[] { A, A, A, a, a, A, a, A, A }));
            thisMap.Add('b', new BitArray(new bool[] { A, A, A, a, a, A, A }));
            thisMap.Add('g', new BitArray(new bool[] { A, A, A, a, A, a, a }));
            thisMap.Add('?', new BitArray(new bool[] { A, A, A, a, A, a, A, a, a, a }));
            thisMap.Add('>', new BitArray(new bool[] { A, A, A, a, A, a, A, a, a, A, a, a, a, a }));
            thisMap.Add('[', new BitArray(new bool[] { A, A, A, a, A, a, A, a, a, A, a, a, a, A }));
            thisMap.Add('\\', new BitArray(new bool[] { A, A, A, a, A, a, A, a, a, A, a, a, A, a }));
            thisMap.Add(']', new BitArray(new bool[] { A, A, A, a, A, a, A, a, a, A, a, a, A, A }));
            thisMap.Add('^', new BitArray(new bool[] { A, A, A, a, A, a, A, a, a, A, a, A, a, a }));
            thisMap.Add('|', new BitArray(new bool[] { A, A, A, a, A, a, A, a, a, A, a, A, a, A }));
            thisMap.Add('}', new BitArray(new bool[] { A, A, A, a, A, a, A, a, a, A, a, A, A, a }));
            thisMap.Add('~', new BitArray(new bool[] { A, A, A, a, A, a, A, a, a, A, a, A, A, A }));
            thisMap.Add('-', new BitArray(new bool[] { A, A, A, a, A, a, A, a, a, A, A }));
            thisMap.Add('S', new BitArray(new bool[] { A, A, A, a, A, a, A, a, A }));
            thisMap.Add('k', new BitArray(new bool[] { A, A, A, a, A, a, A, A, a }));
            thisMap.Add('3', new BitArray(new bool[] { A, A, A, a, A, a, A, A, A, a }));
            thisMap.Add('J', new BitArray(new bool[] { A, A, A, a, A, a, A, A, A, A }));
            thisMap.Add('y', new BitArray(new bool[] { A, A, A, a, A, A, a }));
            thisMap.Add('@', new BitArray(new bool[] { A, A, A, a, A, A, A, a }));
            thisMap.Add('f', new BitArray(new bool[] { A, A, A, a, A, A, A, A }));
            thisMap.Add('j', new BitArray(new bool[] { A, A, A, A, a, a, a }));
            thisMap.Add(',', new BitArray(new bool[] { A, A, A, A, a, a, A, a, a }));
            thisMap.Add('/', new BitArray(new bool[] { A, A, A, A, a, a, A, a, A }));
            thisMap.Add(')', new BitArray(new bool[] { A, A, A, A, a, a, A, A, a, a }));
            thisMap.Add('I', new BitArray(new bool[] { A, A, A, A, a, a, A, A, a, A }));
            thisMap.Add('_', new BitArray(new bool[] { A, A, A, A, a, a, A, A, A, a }));
            thisMap.Add('2', new BitArray(new bool[] { A, A, A, A, a, a, A, A, A, A, a }));
            thisMap.Add('Q', new BitArray(new bool[] { A, A, A, A, a, a, A, A, A, A, A }));
            thisMap.Add('h', new BitArray(new bool[] { A, A, A, A, a, A, a }));
            thisMap.Add('4', new BitArray(new bool[] { A, A, A, A, a, A, A, a, a, a, a, a }));
            thisMap.Add('5', new BitArray(new bool[] { A, A, A, A, a, A, A, a, a, a, a, A }));
            thisMap.Add('7', new BitArray(new bool[] { A, A, A, A, a, A, A, a, a, a, A, a }));
            thisMap.Add('8', new BitArray(new bool[] { A, A, A, A, a, A, A, a, a, a, A, A }));
            thisMap.Add('ñ', new BitArray(new bool[] { A, A, A, A, a, A, A, a, a, A, a, a }));
            thisMap.Add('Ñ', new BitArray(new bool[] { A, A, A, A, a, A, A, a, a, A, a, A, a }));
            thisMap.Add('*', new BitArray(new bool[] { A, A, A, A, a, A, A, a, a, A, a, A, A }));
            thisMap.Add('"', new BitArray(new bool[] { A, A, A, A, a, A, A, a, a, A, A }));
            thisMap.Add('E', new BitArray(new bool[] { A, A, A, A, a, A, A, a, A }));
            thisMap.Add('R', new BitArray(new bool[] { A, A, A, A, a, A, A, A, a }));
            thisMap.Add('T', new BitArray(new bool[] { A, A, A, A, a, A, A, A, A }));
            thisMap.Add('r', new BitArray(new bool[] { A, A, A, A, A }));
            _encodeMaps.Add(EncodeMappings.FullCaseFull, thisMap);
            #endregion

            // -- Upper Case Exc Map --
            #region "Upper Case Exc Map"
            thisMap = new Dictionary<char, BitArray>();
            thisMap.Add('A', new BitArray(new bool[] { a, a, a, a }));
            thisMap.Add('C', new BitArray(new bool[] { a, a, a, A, a }));
            thisMap.Add('W', new BitArray(new bool[] { a, a, a, A, A, a, a, A }));
            thisMap.Add('X', new BitArray(new bool[] { a, a, a, A, A, a, A, a }));
            thisMap.Add('Z', new BitArray(new bool[] { a, a, a, A, A, a, A, A }));
            thisMap.Add('H', new BitArray(new bool[] { a, a, a, A, A, A }));
            thisMap.Add('O', new BitArray(new bool[] { a, a, A, a, a }));
            thisMap.Add('D', new BitArray(new bool[] { a, a, A, a, A }));
            thisMap.Add('U', new BitArray(new bool[] { a, a, A, A, a, a }));
            thisMap.Add('B', new BitArray(new bool[] { a, a, A, A, a, A }));
            thisMap.Add('M', new BitArray(new bool[] { a, a, A, A, A }));
            thisMap.Add('S', new BitArray(new bool[] { a, A, a, a, a }));
            thisMap.Add('J', new BitArray(new bool[] { a, A, a, a, A, a }));
            thisMap.Add('I', new BitArray(new bool[] { a, A, a, a, A, A }));
            thisMap.Add('E', new BitArray(new bool[] { a, A, a, A, a }));
            thisMap.Add('R', new BitArray(new bool[] { a, A, a, A, A }));
            thisMap.Add('Q', new BitArray(new bool[] { a, A, A, a, a, a, a }));
            thisMap.Add('V', new BitArray(new bool[] { a, A, A, a, a, a, A }));
            thisMap.Add('Ñ', new BitArray(new bool[] { a, A, A, a, a, A, a, a }));
            thisMap.Add('K', new BitArray(new bool[] { a, A, A, a, a, A, a, A }));
            thisMap.Add('F', new BitArray(new bool[] { a, A, A, a, a, A, A }));
            thisMap.Add('T', new BitArray(new bool[] { a, A, A, a, A }));
            thisMap.Add('P', new BitArray(new bool[] { a, A, A, A, a, a }));
            thisMap.Add('Y', new BitArray(new bool[] { a, A, A, A, a, A, a }));
            thisMap.Add('G', new BitArray(new bool[] { a, A, A, A, a, A, A }));
            thisMap.Add('N', new BitArray(new bool[] { a, A, A, A, A, a }));
            thisMap.Add('L', new BitArray(new bool[] { a, A, A, A, A, A }));
            thisMap.Add(' ', new BitArray(new bool[] { A }));
            _encodeMaps.Add(EncodeMappings.UpperCaseExc, thisMap);
            #endregion

            // -- Upper Case Full Map --
            #region "Upper Case Full Map"
            thisMap = new Dictionary<char, BitArray>();
            thisMap.Add('.', new BitArray(new bool[] { a, a, a, a }));
            thisMap.Add('A', new BitArray(new bool[] { a, a, a, A, a }));
            thisMap.Add('G', new BitArray(new bool[] { a, a, a, A, A, a, a }));
            thisMap.Add('(', new BitArray(new bool[] { a, a, a, A, A, a, A, a }));
            thisMap.Add(';', new BitArray(new bool[] { a, a, a, A, A, a, A, A, a }));
            thisMap.Add('\'', new BitArray(new bool[] { a, a, a, A, A, a, A, A, A }));
            thisMap.Add('C', new BitArray(new bool[] { a, a, a, A, A, A }));
            thisMap.Add('O', new BitArray(new bool[] { a, a, A, a, a, a }));
            thisMap.Add('1', new BitArray(new bool[] { a, a, A, a, a, A, a }));
            thisMap.Add('H', new BitArray(new bool[] { a, a, A, a, a, A, A }));
            thisMap.Add('D', new BitArray(new bool[] { a, a, A, a, A, a }));
            thisMap.Add('U', new BitArray(new bool[] { a, a, A, a, A, A, a }));
            thisMap.Add('B', new BitArray(new bool[] { a, a, A, a, A, A, A }));
            thisMap.Add('6', new BitArray(new bool[] { a, a, A, A, a, a, a, a, a }));
            thisMap.Add('W', new BitArray(new bool[] { a, a, A, A, a, a, a, a, A }));
            thisMap.Add('X', new BitArray(new bool[] { a, a, A, A, a, a, a, A, a }));
            thisMap.Add('Z', new BitArray(new bool[] { a, a, A, A, a, a, a, A, A }));
            thisMap.Add('¿', new BitArray(new bool[] { a, a, A, A, a, a, A, a, a }));
            thisMap.Add('$', new BitArray(new bool[] { a, a, A, A, a, a, A, a, A, a, a }));
            thisMap.Add('%', new BitArray(new bool[] { a, a, A, A, a, a, A, a, A, a, A }));
            thisMap.Add('&', new BitArray(new bool[] { a, a, A, A, a, a, A, a, A, A, a }));
            thisMap.Add('+', new BitArray(new bool[] { a, a, A, A, a, a, A, a, A, A, A }));
            thisMap.Add('<', new BitArray(new bool[] { a, a, A, A, a, a, A, A, a, a, a }));
            thisMap.Add('=', new BitArray(new bool[] { a, a, A, A, a, a, A, A, a, a, A }));
            thisMap.Add('>', new BitArray(new bool[] { a, a, A, A, a, a, A, A, a, A, a }));
            thisMap.Add('[', new BitArray(new bool[] { a, a, A, A, a, a, A, A, a, A, A }));
            thisMap.Add('\\', new BitArray(new bool[] { a, a, A, A, a, a, A, A, A, a, a }));
            thisMap.Add(']', new BitArray(new bool[] { a, a, A, A, a, a, A, A, A, a, A }));
            thisMap.Add('^', new BitArray(new bool[] { a, a, A, A, a, a, A, A, A, A, a }));
            thisMap.Add('{', new BitArray(new bool[] { a, a, A, A, a, a, A, A, A, A, A }));
            thisMap.Add('M', new BitArray(new bool[] { a, a, A, A, a, A }));
            thisMap.Add('#', new BitArray(new bool[] { a, a, A, A, A, a, a }));
            thisMap.Add('?', new BitArray(new bool[] { a, a, A, A, A, a, A }));
            thisMap.Add('S', new BitArray(new bool[] { a, a, A, A, A, A }));
            thisMap.Add(':', new BitArray(new bool[] { a, A, a, a, a, a }));
            thisMap.Add('-', new BitArray(new bool[] { a, A, a, a, a, A, a, a }));
            thisMap.Add('3', new BitArray(new bool[] { a, A, a, a, a, A, a, A }));
            thisMap.Add('J', new BitArray(new bool[] { a, A, a, a, a, A, A }));
            thisMap.Add(',', new BitArray(new bool[] { a, A, a, a, A, a }));
            thisMap.Add('|', new BitArray(new bool[] { a, A, a, a, A, A, a, a, a, a, a }));
            thisMap.Add('}', new BitArray(new bool[] { a, A, a, a, A, A, a, a, a, a, A }));
            thisMap.Add('~', new BitArray(new bool[] { a, A, a, a, A, A, a, a, a, A, a }));
            thisMap.Add('Ñ', new BitArray(new bool[] { a, A, a, a, A, A, a, a, a, A, A }));
            thisMap.Add('4', new BitArray(new bool[] { a, A, a, a, A, A, a, a, A }));
            thisMap.Add(')', new BitArray(new bool[] { a, A, a, a, A, A, a, A }));
            thisMap.Add('I', new BitArray(new bool[] { a, A, a, a, A, A, A }));
            thisMap.Add('/', new BitArray(new bool[] { a, A, a, A, a, a }));
            thisMap.Add('_', new BitArray(new bool[] { a, A, a, A, a, A, a }));
            thisMap.Add('2', new BitArray(new bool[] { a, A, a, A, a, A, A, a }));
            thisMap.Add('Q', new BitArray(new bool[] { a, A, a, A, a, A, A, A }));
            thisMap.Add('5', new BitArray(new bool[] { a, A, a, A, A, a, a, a, a }));
            thisMap.Add('7', new BitArray(new bool[] { a, A, a, A, A, a, a, a, A }));
            thisMap.Add('8', new BitArray(new bool[] { a, A, a, A, A, a, a, A, a }));
            thisMap.Add('*', new BitArray(new bool[] { a, A, a, A, A, a, a, A, A }));
            thisMap.Add('¡', new BitArray(new bool[] { a, A, a, A, A, a, A }));
            thisMap.Add('E', new BitArray(new bool[] { a, A, a, A, A, A }));
            thisMap.Add('@', new BitArray(new bool[] { a, A, A, a, a }));
            thisMap.Add('R', new BitArray(new bool[] { a, A, A, a, A, a }));
            thisMap.Add('T', new BitArray(new bool[] { a, A, A, a, A, A }));
            thisMap.Add('"', new BitArray(new bool[] { a, A, A, A, a, a, a, a }));
            thisMap.Add('V', new BitArray(new bool[] { a, A, A, A, a, a, a, A }));
            thisMap.Add('P', new BitArray(new bool[] { a, A, A, A, a, a, A }));
            thisMap.Add('!', new BitArray(new bool[] { a, A, A, A, a, A }));
            thisMap.Add('0', new BitArray(new bool[] { a, A, A, A, A, a, a, a }));
            thisMap.Add('F', new BitArray(new bool[] { a, A, A, A, A, a, a, A }));
            thisMap.Add('Y', new BitArray(new bool[] { a, A, A, A, A, a, A, a }));
            thisMap.Add('9', new BitArray(new bool[] { a, A, A, A, A, a, A, A, a }));
            thisMap.Add('K', new BitArray(new bool[] { a, A, A, A, A, a, A, A, A }));
            thisMap.Add('N', new BitArray(new bool[] { a, A, A, A, A, A, a }));
            thisMap.Add('L', new BitArray(new bool[] { a, A, A, A, A, A, A }));
            thisMap.Add(' ', new BitArray(new bool[] { A }));
            _encodeMaps.Add(EncodeMappings.UpperCaseFull, thisMap);
            #endregion

            // -- Lower Case Exc Map --
            #region "Lower Case Exc Map"
            thisMap = new Dictionary<char, BitArray>();
            thisMap.Add('g', new BitArray(new bool[] { a, a, a, a, a, a }));
            thisMap.Add('y', new BitArray(new bool[] { a, a, a, a, a, A }));
            thisMap.Add('x', new BitArray(new bool[] { a, a, a, a, A, a, a, a }));
            thisMap.Add('k', new BitArray(new bool[] { a, a, a, a, A, a, a, A }));
            thisMap.Add('f', new BitArray(new bool[] { a, a, a, a, A, a, A }));
            thisMap.Add('j', new BitArray(new bool[] { a, a, a, a, A, A }));
            thisMap.Add('r', new BitArray(new bool[] { a, a, a, A }));
            thisMap.Add('e', new BitArray(new bool[] { a, a, A }));
            thisMap.Add('i', new BitArray(new bool[] { a, A, a, a }));
            thisMap.Add('n', new BitArray(new bool[] { a, A, a, A }));
            thisMap.Add('a', new BitArray(new bool[] { a, A, A }));
            thisMap.Add('s', new BitArray(new bool[] { A, a, a, a }));
            thisMap.Add('m', new BitArray(new bool[] { A, a, a, A, a }));
            thisMap.Add('c', new BitArray(new bool[] { A, a, a, A, A }));
            thisMap.Add('h', new BitArray(new bool[] { A, a, A, a, a, a }));
            thisMap.Add('ñ', new BitArray(new bool[] { A, a, A, a, a, A, a, a, a, A }));
            thisMap.Add('w', new BitArray(new bool[] { A, a, A, a, a, A, a, a, A }));
            thisMap.Add('z', new BitArray(new bool[] { A, a, A, a, a, A, a, A }));
            thisMap.Add('v', new BitArray(new bool[] { A, a, A, a, a, A, A }));
            thisMap.Add('d', new BitArray(new bool[] { A, a, A, a, A }));
            thisMap.Add('u', new BitArray(new bool[] { A, a, A, A, a }));
            thisMap.Add('l', new BitArray(new bool[] { A, a, A, A, A }));
            thisMap.Add('o', new BitArray(new bool[] { A, A, a, a }));
            thisMap.Add('t', new BitArray(new bool[] { A, A, a, A, a }));
            thisMap.Add('p', new BitArray(new bool[] { A, A, a, A, A, a }));
            thisMap.Add('q', new BitArray(new bool[] { A, A, a, A, A, A, a }));
            thisMap.Add('b', new BitArray(new bool[] { A, A, a, A, A, A, A }));
            thisMap.Add(' ', new BitArray(new bool[] { A, A, A }));
            _encodeMaps.Add(EncodeMappings.LowerCaseExc, thisMap);
            #endregion

            // -- Lower Case Full Map --
            #region "Lower Case Full Map"
            thisMap = new Dictionary<char, BitArray>();
            thisMap.Add('e', new BitArray(new bool[] { a, a, a }));
            thisMap.Add('i', new BitArray(new bool[] { a, a, A, a }));
            thisMap.Add('n', new BitArray(new bool[] { a, a, A, A }));
            thisMap.Add('a', new BitArray(new bool[] { a, A, a }));
            thisMap.Add('s', new BitArray(new bool[] { a, A, A, a }));
            thisMap.Add('m', new BitArray(new bool[] { a, A, A, A, a }));
            thisMap.Add('c', new BitArray(new bool[] { a, A, A, A, A }));
            thisMap.Add('¡', new BitArray(new bool[] { A, a, a, a, a, a, a, a }));
            thisMap.Add('"', new BitArray(new bool[] { A, a, a, a, a, a, a, A, a }));
            thisMap.Add('*', new BitArray(new bool[] { A, a, a, a, a, a, a, A, A, a }));
            thisMap.Add('9', new BitArray(new bool[] { A, a, a, a, a, a, a, A, A, A }));
            thisMap.Add('!', new BitArray(new bool[] { A, a, a, a, a, a, A }));
            thisMap.Add('.', new BitArray(new bool[] { A, a, a, a, a, A }));
            thisMap.Add('d', new BitArray(new bool[] { A, a, a, a, A }));
            thisMap.Add('u', new BitArray(new bool[] { A, a, a, A, a }));
            thisMap.Add('0', new BitArray(new bool[] { A, a, a, A, A, a, a, a, a }));
            thisMap.Add('w', new BitArray(new bool[] { A, a, a, A, A, a, a, a, A }));
            thisMap.Add('z', new BitArray(new bool[] { A, a, a, A, A, a, a, A }));
            thisMap.Add('(', new BitArray(new bool[] { A, a, a, A, A, a, A, a, a, a }));
            thisMap.Add(';', new BitArray(new bool[] { A, a, a, A, A, a, A, a, a, A, a }));
            thisMap.Add('\'', new BitArray(new bool[] { A, a, a, A, A, a, A, a, a, A, A }));
            thisMap.Add('1', new BitArray(new bool[] { A, a, a, A, A, a, A, a, A }));
            thisMap.Add('x', new BitArray(new bool[] { A, a, a, A, A, a, A, A, a }));
            thisMap.Add('6', new BitArray(new bool[] { A, a, a, A, A, a, A, A, A, a, a }));
            thisMap.Add('¿', new BitArray(new bool[] { A, a, a, A, A, a, A, A, A, a, A }));
            thisMap.Add('\\', new BitArray(new bool[] { A, a, a, A, A, a, A, A, A, A, a, a }));
            thisMap.Add('$', new BitArray(new bool[] { A, a, a, A, A, a, A, A, A, A, a, A, a }));
            thisMap.Add('%', new BitArray(new bool[] { A, a, a, A, A, a, A, A, A, A, a, A, A }));
            thisMap.Add('&', new BitArray(new bool[] { A, a, a, A, A, a, A, A, A, A, A, a, a }));
            thisMap.Add('+', new BitArray(new bool[] { A, a, a, A, A, a, A, A, A, A, A, a, A }));
            thisMap.Add('<', new BitArray(new bool[] { A, a, a, A, A, a, A, A, A, A, A, A, a }));
            thisMap.Add('=', new BitArray(new bool[] { A, a, a, A, A, a, A, A, A, A, A, A, A }));
            thisMap.Add('v', new BitArray(new bool[] { A, a, a, A, A, A, a }));
            thisMap.Add('q', new BitArray(new bool[] { A, a, a, A, A, A, A }));
            thisMap.Add('o', new BitArray(new bool[] { A, a, A, a }));
            thisMap.Add('l', new BitArray(new bool[] { A, a, A, A, a }));
            thisMap.Add('t', new BitArray(new bool[] { A, a, A, A, A }));
            thisMap.Add(' ', new BitArray(new bool[] { A, A, a }));
            thisMap.Add('p', new BitArray(new bool[] { A, A, A, a, a, a }));
            thisMap.Add('b', new BitArray(new bool[] { A, A, A, a, a, A, a }));
            thisMap.Add('#', new BitArray(new bool[] { A, A, A, a, a, A, A, a, a }));
            thisMap.Add('?', new BitArray(new bool[] { A, A, A, a, a, A, A, a, A }));
            thisMap.Add('>', new BitArray(new bool[] { A, A, A, a, a, A, A, A, a, a, a, a, a }));
            thisMap.Add('[', new BitArray(new bool[] { A, A, A, a, a, A, A, A, a, a, a, a, A }));
            thisMap.Add(']', new BitArray(new bool[] { A, A, A, a, a, A, A, A, a, a, a, A, a }));
            thisMap.Add('^', new BitArray(new bool[] { A, A, A, a, a, A, A, A, a, a, a, A, A }));
            thisMap.Add('{', new BitArray(new bool[] { A, A, A, a, a, A, A, A, a, a, A, a, a }));
            thisMap.Add('|', new BitArray(new bool[] { A, A, A, a, a, A, A, A, a, a, A, a, A }));
            thisMap.Add('}', new BitArray(new bool[] { A, A, A, a, a, A, A, A, a, a, A, A, a }));
            thisMap.Add('~', new BitArray(new bool[] { A, A, A, a, a, A, A, A, a, a, A, A, A }));
            thisMap.Add('-', new BitArray(new bool[] { A, A, A, a, a, A, A, A, a, A }));
            thisMap.Add('k', new BitArray(new bool[] { A, A, A, a, a, A, A, A, A }));
            thisMap.Add('g', new BitArray(new bool[] { A, A, A, a, A, a, a }));
            thisMap.Add('y', new BitArray(new bool[] { A, A, A, a, A, a, A }));
            thisMap.Add('@', new BitArray(new bool[] { A, A, A, a, A, A, a }));
            thisMap.Add('j', new BitArray(new bool[] { A, A, A, a, A, A, A }));
            thisMap.Add(',', new BitArray(new bool[] { A, A, A, A, a, a, a, a }));
            thisMap.Add('f', new BitArray(new bool[] { A, A, A, A, a, a, a, A }));
            thisMap.Add('3', new BitArray(new bool[] { A, A, A, A, a, a, A, a, a, a }));
            thisMap.Add('ñ', new BitArray(new bool[] { A, A, A, A, a, a, A, a, a, A }));
            thisMap.Add('_', new BitArray(new bool[] { A, A, A, A, a, a, A, a, A }));
            thisMap.Add('/', new BitArray(new bool[] { A, A, A, A, a, a, A, A }));
            thisMap.Add(')', new BitArray(new bool[] { A, A, A, A, a, A, a, a, a, a }));
            thisMap.Add('2', new BitArray(new bool[] { A, A, A, A, a, A, a, a, a, A }));
            thisMap.Add('4', new BitArray(new bool[] { A, A, A, A, a, A, a, a, A, a, a }));
            thisMap.Add('5', new BitArray(new bool[] { A, A, A, A, a, A, a, a, A, a, A }));
            thisMap.Add('7', new BitArray(new bool[] { A, A, A, A, a, A, a, a, A, A, a }));
            thisMap.Add('8', new BitArray(new bool[] { A, A, A, A, a, A, a, a, A, A, A }));
            thisMap.Add(':', new BitArray(new bool[] { A, A, A, A, a, A, a, A }));
            thisMap.Add('h', new BitArray(new bool[] { A, A, A, A, a, A, A }));
            thisMap.Add('r', new BitArray(new bool[] { A, A, A, A, A }));
            _encodeMaps.Add(EncodeMappings.LowerCaseFull, thisMap);
            #endregion

            // Devolver los Encode Maps (Mapas de Codificación)
            return _encodeMaps;
        }
    }
}
